//-------------------------------------------------------------------------------------
// <copyright file="EmbedUninstallProperties.cs" company="Microsoft">
//      Copyright (c) Microsoft Corporation. All rights reserved.
//      THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, 
//      EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED 
//      WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
// </copyright>
// <author>Greg Beech</author>
// <email>gregbee@microsoft.com</email>
// <date>2004-04-15</date>
// <summary>
//      Uninstalls an MSI package.
// </summary>  
//-------------------------------------------------------------------------------------

namespace Microsoft.Sdc.Tasks.Msi
{
    #region Using directives

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Xml;

    #endregion

    #region Class Comments
    /// <summary>
    /// Uninstalls an MSI package.
    /// </summary>
    /// <remarks>
    /// <code><![CDATA[<EmbedUninstallProperties MsiPath="msiPath" ProductCode="productCode" LogFile="logFile" LogOptions="logOptions" UserInterfaceLevel="userInterfaceLevel" LoadUserProfile="loadUserProfile" PropertyFiles="propertyFiles" Properties="properties" Features="features" />]]></code>
    /// <para>where:</para>
    /// <para><i>msiPath (Required*)</i></para>
    /// <para>
    /// The path to the MSI to uninstall.
    /// </para>
    /// <para><i>productCode (Required*)</i></para>
    /// <para>
    /// The GUID product code of the product to uninstall.
    /// </para>
    /// <para><i>logFile (Required)</i></para>
    /// <para>
    /// The path to the log file for the uninstallation. The recommended file name is the name of the MSI
    /// with the extension *.uninstall.log.
    /// </para>
    /// <para><i>logOptions</i></para>
    /// <para>
    /// A delimited list of logging options. Possible values are: Default, StatusMessages, Warnings, Errors,
    /// ActionStart, ActionSpecificRequests, UserRequests, InitialParameters, OutOfMemory, TerminalProperties,
    /// Verbose, AppendLog, FlushEachLine, AllInformation. The default is Default. Please see the
    /// <see cref="Microsoft.Sdc.Tasks.Msi.MsiTaskBase.MsiLoggingOptions"/> documentation for
    /// further information.
    /// </para>
    /// <para><i>userInterfaceLevel</i></para>
    /// <para>
    /// The user interface level displayed by MsiExec during the installation. Possible values are: 
    /// None, Basic, ReducedWithModalDialog, FullWithModalDialog, NoneWithModalDialog, BasicWithModalDialog,
    /// BasicWithNoModalDialogs. The default is None. Please see the 
    /// <see cref="Microsoft.Sdc.Tasks.Msi.MsiTaskBase.MsiExecUILevel"/> documentation for
    /// further information.
    /// </para>
    /// <para><i>loadUserProfile</i></para>
    /// <para>
    /// <b>true</b> if the user's profile is loaded during the processing of the MSI, or <b>false</b> otherwise.
    /// This may be needed for some custom uninstallation actions such as configuring ports and channels in 
    /// Microsoft BizTalk Server. The default is <b>false</b>.
    /// </para>
    /// <para><i>propertyFiles</i></para>
    /// <para>
    /// A delimited list of XML property files that provide uninstallation properties for the MSI. 
    /// Multiple property files are allowed so that you can have a hierarchy - the first file provides a base set of properties
    /// (e.g. environmental properties for a particular rig) and subsequent files can override these to provide a more
    /// specific property or add new properties (e.g. properties for a machine, then properties for an individual MSI).
    /// </para>
    /// <para><i>properties</i></para>
    /// <para>
    /// A delimited list of uninstallation properties in the format Name=Value. If any property files have been 
    /// specified, then the properties specified here are seen as the most significant and can overwrite 
    /// any of the property values specified in the files.
    /// </para>
    /// <para>
    /// <b>*</b> - Either <i>msiPath</i> or <i>productCode</i> must be provided. If both are provided then 
    /// <i>msiPath</i> takes precedence and <i>productCode</i> is ignored. If neither are provided then the
    /// task will throw an exception when it executes.
    /// </para>
    /// </remarks>
    /// <example>
    /// <code><![CDATA[
    /// <Project>
    ///     <Target Name="Test">
    ///         <Msi.EmbedUninstallProperties 
    ///             MsiPath="C:\Build\Msi\Packages\MyPackage.msi" 
    ///             ProductCode="b6b6f41c-fd3e-4b5b-8a73-c59494974990" 
    ///             LogFile="C:\Build\Msi\Packages\MyPackage.uninstall.log" 
    ///             LogOptions="Default;Verbose" 
    ///             UserInterfaceLevel="None" 
    ///             LoadUserProfile="true" 
    ///             PropertyFiles="C:\Build\Properties\Global.xml;C:\Build\Properties\Rig4.xml" 
    ///             Properties="INSTALLDIR=C:\Install;DOMAIN=rig4;MACHINE=r4app01" >
    ///             <Output TaskParameter="ExecArguments" PropertyName="ExecArguments" />
    ///         </Msi.EmbedUninstallProperties>
    ///     </Target>
    /// </Project>
    /// ]]></code>   
    /// A sample property file is shown below. Note that you must include the namespace for the file to
    /// be parsed correctly.
    /// <code><![CDATA[
    /// <Properties xmlns="urn:sdc-microsoft-com:deployment:properties:v2.0">
    ///     <Property Name="MY_PROPERTY" Value="some value" />
    ///     <Property Name="ANOTHER_PROPERTY" Value="some other value" />
    ///     <Property Name="SOMETHING_ELSE" Value="hello world" />
    ///     ... etc ...
    /// </Properties>
    /// ]]></code>  
    /// </example>
    #endregion
    public sealed class EmbedUninstallProperties : MsiTaskBase
    {
        #region Member Variables

        /// <summary>
        /// internal variable
        /// </summary>
        private bool embedProperties = false;

        /// <summary>
        /// internal variable
        /// </summary>
        private string msiExecArguments;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the EmbedUninstallProperties class.
        /// </summary>
        public EmbedUninstallProperties()
        {
        }

        #endregion

        #region Properties

        /// <summary>
        /// Specifies if Properties should be embedded into the MSI before installation.
        /// </summary>
        /// <remarks>
        /// When this property is set to true all properties specified in a property file will 
        /// be embedded into the MSI unless they have an additional attribute <b>Embed</b> set to false.
        /// All properties with Embed set to false are discarded.
        /// </remarks>
        /// <value>
        /// True or False.
        /// </value>
        public bool EmbedProperties
        {
            get
            {
                return this.embedProperties;
            }

            set
            {
                this.embedProperties = value;
            }
        }

        /// <summary>
        /// The argument string to use with the MSI file
        /// </summary>
        [Microsoft.Build.Framework.Output]
        public string ExecArguments
        {
            get
            {
                return this.msiExecArguments;
            }

            set
            {
                this.msiExecArguments = value;
            }
        }

        #endregion

        #region Protected Methods

        /// <summary>
        /// Executes the task to embed the properties into the MSI and return the argument string
        /// </summary>
        /// <summary>
        /// Performs the action of this task.
        /// </summary>
        protected override void InternalExecute()
        {
            this.msiExecArguments = BuildUninstallArgumentsAndEmbedProperties(this.embedProperties);
        }
        #endregion
    }
}